home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / DBio / DSequence.cpp < prev    next >
Encoding:
Text File  |  1995-12-17  |  34.3 KB  |  1,488 lines  |  [TEXT/R*ch]

  1. // DSequence.cp 
  2. // d.g.gilbert
  3.  
  4.  
  5.  
  6. #include "DSequence.h"
  7. #include "DSeqFile.h"
  8. #include "DREnzyme.h"
  9. #include <ncbi.h>
  10. #include <dgg.h>
  11. #include <DUtil.h>
  12. #include <DFile.h>
  13. #include "ureadseq.h"
  14.  
  15.  
  16. char* DSequence::kConsensus = "Consensus";
  17. char  DSequence::indelHard = '-';
  18. char  DSequence::indelSoft = '~';
  19. char  DSequence::indelEdge = '.';
  20.  
  21.  
  22. Local char* gAminos        =    "ABCDEFGHIKLMNPQRSTVWXYZ*_.-~?";
  23. Local char* gIubbase    = "ACGTUMRWSYKVHDBXN_.-*~?";     //did include ".", for what?
  24. Local char* gPrimenuc    = "ACGTU_.-*~?";
  25. Local char* protonly    = "EFIPQZ";
  26. Local char* stdsymbols= "_.-*?";
  27. Local char* allsymbols= "_.-*?!=/**/[]()!&#$%^&=+;:/|`~'\"\\";
  28. Local char* seqsymbols= allsymbols;
  29. Local Boolean kForWriting    = TRUE;
  30. Local Boolean    kForReading    = FALSE;
  31.  
  32. enum { kSearchNotFound = -1, kMaskOK = 'K', kMaskEmpty = -1 };
  33.  
  34.  
  35.     
  36. long DSequence::NucleicBits(char nuc)
  37. {
  38.     //char nuc= toupper(nuc);
  39.     switch (nuc) {
  40.         case 'a': case 'A': return kMaskA;  
  41.         case 'c': case 'C': return kMaskC;   
  42.         case 'g': case 'G': return kMaskG;   
  43.         case 't': case 'T': return kMaskT;   
  44.         case 'u': case 'U': return kMaskU;  // ==  ( kMaskT | kMaskExtra); 
  45.         case 'y': case 'Y': return (kMaskC | kMaskT);  
  46.         case 'k': case 'K': return (kMaskG | kMaskT);  
  47.         case 's': case 'S': return (kMaskG | kMaskC);  
  48.         case 'r': case 'R': return (kMaskG | kMaskA);  
  49.         case 'm': case 'M': return (kMaskA | kMaskC);  
  50.         case 'w': case 'W': return (kMaskA | kMaskT);  
  51.         case 'h': case 'H': return (kMaskA | kMaskC | kMaskT);  
  52.         case 'b': case 'B': return (kMaskG | kMaskC | kMaskT);  
  53.         case 'v': case 'V': return (kMaskG | kMaskC | kMaskA);  
  54.         case 'd': case 'D': return (kMaskG | kMaskT | kMaskA);  
  55.         // case '-': return kMaskIndel;   
  56.         case ' ': case '_': return 0;  //? spacers
  57.         case  0 : return 0;  
  58.         // case '.': //indelEdge     
  59.         case 'n': case 'N': return kMaskNucs; 
  60.         default : 
  61.             {
  62.             if (nuc == indelHard || nuc == indelSoft)  return kMaskIndel;
  63.             else if (nuc == indelEdge) return kMaskNucs;
  64.             else return 0; //kMaskNucs;  //?? match all or match none ??
  65.             }
  66.         }
  67. }
  68.  
  69.  
  70. Boolean DSequence::IsNucleicMatch( long xNucBits, long yNucBits)
  71. {
  72.         // note: Indel/spaces match nothing, including other indel/space ...
  73.     return 0 != ( (kMaskNucs & xNucBits) & (kMaskNucs & yNucBits));
  74. }
  75.  
  76.  
  77. char DSequence::NucleicConsensus( long xNucBits, long yNucBits)
  78.     char nuc; 
  79.     Boolean isrna, indel;
  80.  
  81.     if (xNucBits==0 || yNucBits==0) 
  82.         return ' ';  //?? either a space yields space ?
  83.     else {
  84.         indel= (kMaskIndel == xNucBits || kMaskIndel == yNucBits);
  85.         isrna= (kMaskU == xNucBits || kMaskU == yNucBits);
  86.         switch ( (kMaskNucs & xNucBits) | (kMaskNucs & yNucBits)) {
  87.             case kMaskA: nuc= 'A'; break;
  88.             case kMaskC: nuc= 'C'; break;
  89.             case kMaskG: nuc= 'G'; break;
  90.             case kMaskT: 
  91.                 if (isrna) nuc= 'U'; else nuc= 'T';
  92.                 break;
  93.                     //? do other ambig codes ?
  94.             default:    nuc= '.'; break; //? use this as Consensus other ?
  95.             }
  96.         if (indel) nuc= tolower(nuc); //?
  97.         }
  98.     return nuc;
  99. }
  100.  
  101.  
  102.  
  103. void DSequence::NucleicComplement( Boolean isrna, char* fromSeq, char* toSeq, long len)
  104. {
  105. // note: fromSeq may == toSeq 
  106.     register char b, c;
  107.     Boolean islow;
  108.      while (len--) {
  109.         b= *fromSeq++;
  110.         islow= islower(b);
  111.         if (islow) b= toupper(b);
  112.         switch (b) {
  113.             case 'C': c= 'G'; break;
  114.             case 'G': c= 'C'; break;
  115.             case 'A': if (isrna) c= 'U'; else c= 'T'; break;
  116.             case 'T':
  117.             case 'U': c= 'A'; break;
  118.             case 'R': c= 'Y'; break;
  119.             case 'Y': c= 'R'; break;
  120.             case 'M': c= 'K'; break;
  121.             case 'K': c= 'M'; break;
  122.             case 'S': c= 'S'; break;  // was mistaken 'w'
  123.             case 'W': c= 'W'; break;  // was mistaken 's'
  124.             case 'H': c= 'D'; break;
  125.             case 'D': c= 'H'; break;
  126.             case 'B': c= 'V'; break;
  127.             case 'V': c= 'B'; break;
  128.             default : c= b;   break;
  129.             }
  130.         if (islow) c= tolower(c);
  131.         *toSeq++= c;
  132.         }
  133. }
  134.  
  135.  
  136.  
  137. const char* DSequence::Amino123( char amino1)
  138. {
  139.  switch (toupper( amino1)) {
  140.      case 'A': return "Ala";
  141.      case 'M': return "Met";
  142.      case 'R': return "Arg";
  143.      case 'F': return "Phe";
  144.      case 'N': return "Asn";
  145.      case 'P': return "Pro";
  146.      case 'D': return "Asp";
  147.      case 'S': return "Ser";
  148.      case 'C': return "Cys";
  149.      case 'T': return "Thr";
  150.      case 'Q': return "Gln";
  151.      case 'W': return "Trp";
  152.      case 'E': return "Glu";
  153.      case 'Y': return "Tyr";
  154.      case 'G': return "Gly";
  155.      case 'V': return "Val";
  156.      case 'H': return "His";
  157.      case 'I': return "Ile";
  158.      case 'B': return "Asx";
  159.      case 'L': return "Leu";
  160.      case 'Z': return "Glx";
  161.      case 'K': return "Lys";
  162.      case 'X': return "Xaa";
  163.      case '*': return "End";
  164.      case ' ': return "   ";
  165.      default : return "???"; //??
  166.      }
  167. }
  168.  
  169.  
  170. char DSequence::Amino321( char* amino)
  171. {
  172.     char    aa[4];
  173.     aa[0]= toupper(amino[0]);
  174.     aa[1]= tolower(amino[1]);
  175.     aa[2]= tolower(amino[2]);
  176.     aa[3]= 0;
  177.     
  178.              if (!StrCmp(aa,"Ala")) return 'A';
  179.     else if (!StrCmp(aa,"Met")) return 'M';
  180.     else if (!StrCmp(aa,"Arg")) return 'R';         
  181.     else if (!StrCmp(aa,"Phe")) return 'F';
  182.     else if (!StrCmp(aa,"Asn")) return 'N';       
  183.     else if (!StrCmp(aa,"Pro")) return 'P';
  184.     else if (!StrCmp(aa,"Asp")) return 'D';    
  185.     else if (!StrCmp(aa,"Ser")) return 'S';
  186.     else if (!StrCmp(aa,"Cys")) return 'C';         
  187.     else if (!StrCmp(aa,"Thr")) return 'T';
  188.     else if (!StrCmp(aa,"Gln")) return 'Q';       
  189.     else if (!StrCmp(aa,"Trp")) return 'W';
  190.     else if (!StrCmp(aa,"Glu")) return 'E';    
  191.     else if (!StrCmp(aa,"Tyr")) return 'Y';
  192.     else if (!StrCmp(aa,"Gly")) return 'G';          
  193.     else if (!StrCmp(aa,"Val")) return 'V';
  194.     else if (!StrCmp(aa,"His")) return 'H';
  195.     else if (!StrCmp(aa,"Ile")) return 'I';       
  196.     else if (!StrCmp(aa,"Asx")) return 'B';
  197.     else if (!StrCmp(aa,"Leu")) return 'L';          
  198.     else if (!StrCmp(aa,"Glx")) return 'Z';
  199.     else if (!StrCmp(aa,"Lys")) return 'K';           
  200.     else if (!StrCmp(aa,"End")) return '*';           
  201.     else if (!StrCmp(aa,"   ")) return ' '; //??           
  202.     else return 'X';
  203. }
  204.  
  205.  
  206. char* DSequence::Nucleic23Protein( char* nucs, long nbases)
  207. //!! Need to do this w/ NucBits so ambiguity codes work !!
  208. //!! The CodonTable.codon == acodon should be IsNucleicMatch( bits(codon), bits(acodon)) 
  209. {
  210.     long    i;  //borland 16bit don't like longs for iterators !?
  211.     char  *ap, *kp, *aminos;
  212.  
  213.     if (DCodons::NotAvailable()) return NULL; // (gCodonTable[0].amino == 0)
  214.  
  215.     aminos= StrDup( nucs);
  216.     for (i= 0, ap= aminos; i<nbases; i++) {
  217.         register char c= toupper( *ap);
  218.         if (c=='U') c= 'T';
  219.         *ap++= c;
  220.         }
  221.  
  222.     for (i= 0, ap= aminos, kp= aminos; i<nbases; i++) {
  223.         for (long j=0; j<64; j++)
  224.             if ( MemCmp(DCodons::codon(j), ap, 3) == 0) { //gCodonTable[j].codon
  225.                 *kp++= DCodons::amino(j); // gCodonTable[j].amino;
  226.                 break;
  227.                 }
  228.         }
  229.     *kp= '\0';
  230.     aminos= (char*) MemMore( aminos, kp - aminos + 1);
  231.     return aminos;
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241. // DSequence -----------------
  242.  
  243.  
  244. DSequence::DSequence()
  245. {
  246.     fBases= (char*) MemGet(1,true); 
  247.   fMasks= NULL; //(char*) MemGet(1,true); 
  248.   fMasksOk= false;
  249.     fInfo    = (char*) MemGet(1,true);     
  250.     fName = StrDup("Untitled");         //!? need unique name, eg. Noname-1,noname-2...
  251.     fKind = kOtherSeq;         //? user default
  252.     fLength        = 0;
  253.     fChecksum    = 0;
  254.     fIndex        = 0; //dummy
  255.     fModTime    = gUtil->time();
  256.     fChanged    = TRUE;
  257.     fDeleted    = FALSE; 
  258.     fOpen            = FALSE;
  259.     fSearchRec.targ= NULL;
  260.     fOrigin    = 0;
  261.     fSelStart= 0;
  262.     fSelBases= 0;
  263. }
  264.  
  265.  
  266. DSequence::~DSequence()  
  267. {
  268.     MemFree(fBases);
  269.     MemFree(fMasks);
  270.     MemFree(fInfo);
  271.     MemFree(fName);
  272.     MemFree(fSearchRec.targ);
  273. }
  274.  
  275.  
  276. DObject* DSequence::Clone() // override 
  277. {    
  278.     DSequence* aSeq= (DSequence*) DObject::Clone();
  279.     aSeq->fBases= StrDup( fBases);
  280.     aSeq->fMasks= NULL; aSeq->SetMasks( fMasks); //aSeq->fMasks= StrDup( fMasks);
  281.     aSeq->fInfo=  StrDup( fInfo);
  282.     aSeq->fName=  StrDup( fName);
  283.     aSeq->fSearchRec.targ= StrDup( fSearchRec.targ);
  284.     return aSeq;
  285. }
  286.  
  287. void DSequence::CopyContents( DSequence* fromSeq)
  288. {
  289.     SetBases( fromSeq->fBases); 
  290.     SetMasks( fromSeq->fMasks); 
  291.     SetInfo( fromSeq->fInfo); 
  292.     SetName( fromSeq->fName); 
  293.     fKind            = fromSeq->fKind;          
  294.     fLength        = fromSeq->fLength;
  295.     fChecksum    = fromSeq->fChecksum;
  296.     fModTime    = fromSeq->fModTime;
  297.     fChanged    = fromSeq->fChanged;
  298.     fDeleted    = fromSeq->fDeleted; 
  299.     fOpen            = fromSeq->fOpen;
  300.     fIndex        = fromSeq->fIndex;
  301.     fSearchRec= fromSeq->fSearchRec;
  302.     fSearchRec.targ= StrDup( fromSeq->fSearchRec.targ);
  303. }
  304.  
  305. void DSequence::SetBases( char* theBases)
  306. {
  307.     if (fBases) MemFree(fBases);
  308.     fBases = StrDup(theBases);  
  309.     fLength= StrLen(fBases);
  310.     fMasksOk= false; // assume SetBases allways called before SetMask...
  311. }
  312.  
  313. void DSequence::UpdateBases( char* theBases, long theLength)
  314. {
  315.     fBases =  theBases;  
  316.     fLength= theLength;
  317.     fMasksOk= false; // assume this allways called before SetMask...
  318. }
  319.  
  320.  
  321. void DSequence::SetMasks( char* theMasks)
  322. {
  323.     if (fMasks) MemFree(fMasks);
  324.     if (theMasks) {
  325.         fMasks = StrDup(theMasks);  
  326.         FixMasks();
  327.         }
  328.     else {
  329.         fMasks= NULL;
  330.         fMasksOk= false;
  331.         }
  332. }
  333.  
  334. void DSequence::FixMasks()
  335. {
  336.     ulong i, mlen= 0;
  337.     if (!fMasks) { 
  338.         mlen= 1+fLength;
  339.         fMasks= (char*) MemGet(mlen,true);  
  340.         for (i=0; i<mlen; i++) fMasks[i] |= 0x80; // set high bit so Strxxx sees it as non-null
  341.         fMasks[mlen-1]= 0;
  342.         }
  343.     else { 
  344.         mlen= 1+StrLen(fMasks);
  345.         if (fLength+1 != mlen) {
  346.             fMasks= (char*) Nlm_MemExtend( fMasks, fLength+1, mlen);
  347.             mlen= fLength+1; 
  348.             for (i=0; i<mlen; i++) fMasks[i] |= 0x80; 
  349.             fMasks[mlen-1]= 0;
  350.             } 
  351.         }
  352.     fMasksOk= true;
  353. }
  354.  
  355. short DSequence::MaskAt(long baseindex, short masklevel)
  356. {
  357.     short b = kMaskEmpty;
  358.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength) {
  359.         b= (unsigned char) fMasks[baseindex];
  360.         switch (masklevel) {
  361.             case 0: b &= 0x7f; break; // return full mask - top (0x80) bit
  362.             case 1: b &= 1;  break;  
  363.             case 2: b &= 2;  break;
  364.             case 3: b &= 4;  break;
  365.             case 4: b &= 8;  break;
  366.             default: b = kMaskEmpty; break;
  367.             }
  368.         }
  369.     return b;
  370. }
  371.  
  372.  
  373. inline void SetMaskByte( char& b, short masklevel, short maskval)
  374. {
  375.     switch (masklevel) {
  376.         case 1: if (maskval) b |= 1; else b &= ~1; break;
  377.         case 2: if (maskval) b |= 2; else b &= ~2; break;
  378.         case 3: if (maskval) b |= 4; else b &= ~4; break;
  379.         case 4: if (maskval) b |= 8; else b &= ~8; break;
  380.         // reserve bits 5, 6, 7 & 8 for now 
  381.         // -- 7 & 8 may go unused to store data in printchar form
  382.         default: break;
  383.         }
  384.     //if (b) masklevel--; // debugging b val
  385. }
  386.  
  387. void DSequence::SetMaskAt(long baseindex, short masklevel, short maskval)
  388. {
  389.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength)  
  390.         ::SetMaskByte(fMasks[baseindex],masklevel, maskval);
  391. }
  392.  
  393.  
  394. void DSequence::SetMask(short masklevel, short maskval)
  395. {
  396.     long  baseindex;
  397.     if (fMasks && fMasksOk) 
  398.      for (baseindex=0; baseindex<fLength; baseindex++) 
  399.         ::SetMaskByte(fMasks[baseindex], masklevel, maskval);
  400. }
  401.  
  402.  
  403. inline void FlipMaskByte( char& b, short masklevel)
  404. {
  405.     switch (masklevel) {
  406.         case 1: b ^= 1;  break;  
  407.         case 2: b ^= 2;  break;
  408.         case 3: b ^= 4;  break;
  409.         case 4: b ^= 8;  break;
  410.         default:  break;
  411.         }
  412.     //if (b) masklevel--; // debugging b val
  413. }
  414.  
  415. void DSequence::FlipMaskAt(long baseindex, short masklevel)
  416. {
  417.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength)  
  418.         ::FlipMaskByte(fMasks[baseindex],masklevel);
  419. }
  420.  
  421. void DSequence::FlipMask(short masklevel)
  422. {
  423.     long  baseindex;
  424.     if (fMasks && fMasksOk) 
  425.      for (baseindex=0; baseindex<fLength; baseindex++)  
  426.         FlipMaskByte(fMasks[baseindex],masklevel);
  427. }
  428.  
  429.  
  430. void DSequence::SetInfo( char* theInfo)
  431. {
  432.     if (fInfo) MemFree(fInfo);
  433.     fInfo = StrDup(theInfo);  
  434. }
  435.  
  436. void DSequence::SetName( char* theName)
  437. {
  438.     if (fName) MemFree(fName);
  439.     fName = StrDup(theName);  
  440. }
  441.  
  442. void DSequence::SetKind( short theKind)
  443. {
  444.     fKind= theKind;  
  445. }
  446.  
  447. void DSequence::SetIndex( short theIndex)
  448. {
  449.     fIndex= theIndex;  
  450. }
  451.  
  452. char* DSequence::KindStr() const 
  453. {
  454.     switch (fKind) {
  455.         case kDNA             : return "DNA";
  456.         case kRNA             : return "RNA";
  457.         case kNucleic   : return "Nucleic";
  458.         case kAmino         : return "Protein";
  459.         default                    :
  460.         case kOtherSeq  : return "Unknown";
  461.         }
  462. }
  463.  
  464.  
  465. void DSequence::SetTime( unsigned long theTime)
  466. {
  467.     fModTime= theTime;
  468. }
  469.  
  470. void DSequence::SetOrigin( long theOrigin)
  471. {
  472.     fOrigin= theOrigin;
  473. }
  474.  
  475. void DSequence::Modified()  
  476. {
  477.     fModTime    = gUtil->time();
  478.     fChanged    = TRUE;
  479. }
  480.  
  481. void DSequence::Reformat(short format)
  482. {
  483.     // later...? 
  484. }
  485.  
  486. void DSequence::UpdateFlds()
  487. {
  488.     long         seqlen;
  489.     short     kind;
  490.     unsigned long check;
  491.     fLength= StrLen(fBases);
  492.     GetSeqStats(fBases, fLength, &kind, &check, &seqlen);
  493.     //fValidLength= seqlen; //?? is fLength == StrLen(fBases) or is it <= that, only valid bases??
  494.     fKind            = kind;
  495.     fChecksum    = check;
  496.     fChanged    = FALSE;
  497. }
  498.  
  499.  
  500.  
  501.  
  502.  
  503. void DSequence::SetSelection( long start, long nbases)
  504. {
  505.     fSelStart= start;
  506.     fSelBases= nbases;
  507. }
  508.  
  509. void DSequence::ClearSelection()
  510. {
  511.     fSelStart= 0;
  512.     fSelBases= 0;
  513. }
  514.  
  515. void    DSequence::GetSelection( long& start, long& nbases)
  516. {
  517.     if (fSelBases==0) {
  518.         start= 0;
  519.         nbases= fLength;
  520.         }    
  521.     else if (fLength>0) {
  522.         start= fSelStart;
  523.         nbases= Min( fSelBases, fLength - fSelStart);
  524.         }    
  525.     else {
  526.         start= 0;
  527.         nbases= 0;
  528.         }
  529. }
  530.  
  531.  
  532. DSequence* DSequence::CopyRange()
  533. {  
  534.             //note: start == 0 == 1st position 
  535.     DSequence* aSeq= (DSequence*) Clone();
  536.     if (fSelStart > 0 || fSelBases > 0) {
  537.         char* h= aSeq->fBases;
  538.         char* m= aSeq->fMasks;
  539.         Boolean domask= (fMasks && fMasksOk);
  540.  
  541.         long len= aSeq->fLength;
  542.         if (fSelStart > 0) {
  543.             len -= fSelStart;
  544.             MemMove( h, h + fSelStart, len);
  545.             if (domask) MemMove( m, m + fSelStart, len);
  546.             }
  547.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  548.         h= (char*) MemMore( h, len+1);
  549.         h[len]= '\0'; //((char*)h+len) = '\0';
  550.         aSeq->fBases= h;
  551.         if (domask) {
  552.             m= (char*) MemMore( m, len+1);
  553.             m[len]= '\0';    
  554.             aSeq->fMasks= m;
  555.             }
  556.         }
  557.     aSeq->UpdateFlds();
  558.     aSeq->Modified();
  559.     return aSeq;
  560. }
  561.  
  562.  
  563. DSequence* DSequence::CutRange()
  564. {
  565. /* aSeq.Cutrange means:  
  566.         (a) selected range (fSelStart..fSelStart+fSelBases) is copied into Result; &&
  567.         (b) selected range is removed from this
  568. */
  569.  
  570.     DSequence* aSeq= CopyRange();
  571.     if (fSelStart > 0 || fSelBases > 0) {
  572.         if (fSelStart<0) fSelStart= 0;
  573.         char* h= this->fBases;
  574.         char* m= this->fMasks;
  575.         Boolean domask= (fMasks && fMasksOk);
  576.         long len= this->fLength;
  577.         long top= len - fSelStart - fSelBases;
  578.         if (fSelBases > 0 && fSelBases < len) {
  579.             MemMove( h+fSelStart, h+fSelStart+fSelBases, top);
  580.             if (domask) MemMove( m+fSelStart, m+fSelStart+fSelBases, top);
  581.             }
  582.         len= fSelStart + top;
  583.         h= (char*) MemMore( h, len+1);
  584.         *((char*)h+len)= '\0';       //h[len]= '\0';
  585.         this->fBases= h;
  586.         if (domask) {
  587.             m= (char*) MemMore( m, len+1);
  588.             *((char*)m+len)= '\0';    
  589.             this->fMasks= m;
  590.             }
  591.         }
  592.     UpdateFlds();    
  593.     Modified();
  594.     return aSeq;
  595. }
  596.  
  597. void DSequence::InsertSpacers( long insertPoint, long insertCount, char spacer)
  598.     long i;
  599.     char *cp;
  600.     char* h= this->fBases;
  601.     char* m= this->fMasks;
  602.     Boolean domask= (fMasks && fMasksOk);
  603.     long len= this->fLength;
  604.     if (insertPoint<0) insertPoint= 0;
  605.     else if (insertPoint>len-1) insertPoint= len-1;
  606.     h= (char*) MemMore( h, len+insertCount+1);
  607.     cp = h+insertPoint;
  608.     MemMove( cp+insertCount, cp, len-insertPoint);
  609.     for ( i= 0; i<insertCount; i++)  *cp++= spacer;
  610.     h[len+insertCount]= '\0';
  611.     this->fBases= h;
  612.     if (domask) {
  613.         m= (char*) MemMore( m, len+insertCount+1);
  614.         cp = m+insertPoint;
  615.         char cmask= *cp;
  616.         MemMove( cp+insertCount, cp, len-insertPoint);
  617.         for ( i= 0; i<insertCount; i++)  *cp++= cmask;
  618.         m[len+insertCount]= '\0';
  619.         this->fMasks= m;
  620.         }
  621.     this->UpdateFlds();    
  622.     this->Modified();
  623. }
  624.  
  625.  
  626. DSequence* DSequence::PasteBases( long insertPoint, char* fromBases, char* fromMasks)
  627.     long add;
  628.     DSequence* aSeq= (DSequence*) Clone();
  629.     if (fromBases) add= StrLen( fromBases);  else add= 0;
  630.     if (add>0) {
  631.         char* h= aSeq->fBases;
  632.         char* m= aSeq->fMasks;
  633.         Boolean domask= (fMasks && fMasksOk);
  634.         long len = aSeq->fLength;
  635.         if (insertPoint<=0) {
  636.             fromBases= StrDup( fromBases);
  637.             StrExtendCat( &fromBases, h);
  638.             MemFree( h);
  639.             h= fromBases;
  640.             if (domask && fromMasks) {
  641.                 fromMasks= StrDup( fromMasks);
  642.                 StrExtendCat( &fromMasks, m);
  643.                 MemFree( m);
  644.                 m= fromMasks;
  645.                 }
  646.             }        
  647.         else if (insertPoint>=len) { 
  648.             StrExtendCat( &h, fromBases);
  649.             if (domask) StrExtendCat( &m, fromMasks);
  650.             }
  651.         else { 
  652.             h= (char*) MemMore( h, len+add);
  653.             MemMove( h+insertPoint+add, h+insertPoint, len-insertPoint);
  654.             MemMove( h+insertPoint+add, fromBases, add);
  655.             *((char*)h+len+add)= '\0';
  656.             if (domask) {
  657.                 m= (char*) MemMore( m, len+add);
  658.                 MemMove( m+insertPoint+add, m+insertPoint, len-insertPoint);
  659.                 MemMove( m+insertPoint+add, fromMasks, add);
  660.                 *((char*)m+len+add)= '\0';
  661.                 }
  662.             }
  663.         aSeq->fBases= h;
  664.         aSeq->fMasks= m;
  665.         }
  666.     aSeq->UpdateFlds();    
  667.     aSeq->Modified();
  668.     return aSeq;
  669. }
  670.  
  671.  
  672. DSequence* DSequence::Reverse()
  673. {
  674.     long i;
  675.     DSequence* aSeq= (DSequence*) Clone();    
  676.     if (fSelStart < 0) fSelStart= 0;
  677.     long len= aSeq->fLength - fSelStart;
  678.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  679.     char* pc= this->fBases+fSelStart + len;
  680.     char* pr= aSeq->fBases+fSelStart;
  681.     for (i= 0; i<len; i++) *pr++= *--pc;
  682.     Boolean domask= (fMasks && fMasksOk);
  683.     if (domask) {
  684.         pc= this->fMasks+fSelStart + len;
  685.         pr= aSeq->fMasks+fSelStart;
  686.         for (i= 0; i<len; i++) *pr++= *--pc;
  687.         }
  688.     aSeq->UpdateFlds();
  689.     aSeq->Modified();
  690.     return aSeq;
  691. }
  692.  
  693.  
  694. DSequence* DSequence::Complement()
  695. // A->T, T->A, G->C, C->G  
  696. {
  697.     Boolean        isrna;
  698.     DSequence* aSeq= (DSequence*) Clone();    
  699.     
  700.     if (fKind == kRNA) isrna= TRUE;
  701.     else if (fKind == kDNA || fKind == kNucleic) isrna= FALSE;
  702.     else return aSeq;    
  703.         
  704.     if (fSelStart < 0) fSelStart= 0;
  705.     long len= aSeq->fLength - fSelStart;
  706.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  707.     char* pc= this->fBases+fSelStart;
  708.     char* pr= aSeq->fBases+fSelStart;
  709.     NucleicComplement( isrna, pc, pr, len);
  710.         
  711.     aSeq->UpdateFlds();
  712.     aSeq->Modified();
  713.     return aSeq;
  714. }
  715.  
  716.  
  717.  
  718. DSequence* DSequence::ChangeCase(Boolean toUpper)
  719. // g->G or G->g
  720. {
  721.     DSequence* aSeq= (DSequence*) Clone();    
  722.     
  723.     if (fSelStart < 0) fSelStart= 0;
  724.     char* h= aSeq->fBases;
  725.     long len= aSeq->fLength - fSelStart;
  726.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  727.     char* pc= this->fBases+fSelStart;
  728.     char* pr= aSeq->fBases+fSelStart;
  729.     
  730.     long i;
  731.     if (toUpper) for (i= 0; i<len; i++) {
  732.         *pr++= toupper(*pc++);
  733.         }
  734.     else for (i= 0; i<len; i++) {
  735.         *pr++= tolower(*pc++);
  736.         }    
  737.         
  738.     aSeq->UpdateFlds();
  739.     aSeq->Modified();
  740.     return aSeq;
  741. }
  742.  
  743. DSequence* DSequence::Dna2Rna(Boolean toRna)
  744. // T->U or U->T 
  745. {
  746.     Boolean        isrna;
  747.     DSequence* aSeq= (DSequence*) Clone();    
  748.     
  749.     if (fKind==kRNA) isrna= TRUE;
  750.     else if (fKind == kDNA || fKind == kNucleic) isrna= FALSE;
  751.     else return aSeq;    
  752.      
  753.     if (fSelStart < 0) fSelStart= 0;
  754.     long len= aSeq->fLength - fSelStart;
  755.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  756.     char* pc= this->fBases+fSelStart;
  757.     char* pr= aSeq->fBases+fSelStart;
  758.     
  759.     long i;
  760.     char b, c;
  761.     if (toRna) for (i= 0; i<len; i++) {
  762.         b= *pc++;
  763.         if (b=='T') c= 'U';
  764.         else if (b=='t') c= 'u';
  765.         else c= b;
  766.         *pr++= c;
  767.         }
  768.     else for (i= 0; i<len; i++) {
  769.         b= *pc++;
  770.         if (b=='U') c= 'T';
  771.         else if (b=='u') c= 't';
  772.         else c= b;
  773.         *pr++= c;
  774.         }    
  775.         
  776.     aSeq->UpdateFlds();
  777.     aSeq->Modified();
  778.     return aSeq;
  779. }
  780.  
  781.  
  782. DSequence* DSequence::LockIndels( Boolean doLock)
  783. // indelSoft -> indelHard or vice versa 
  784. {    
  785.     char b, c, fromc, toc;
  786.     DSequence* aSeq= (DSequence*) Clone();    
  787.     
  788.     if (fSelStart < 0) fSelStart= 0;
  789.     long  len= aSeq->fLength - fSelStart;
  790.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  791.     char* pc= this->fBases+fSelStart;
  792.     char* pr= aSeq->fBases+fSelStart;
  793.     
  794.     if (doLock) { fromc= indelSoft; toc= indelHard; }
  795.     else { fromc= indelHard; toc= indelSoft; }
  796.     
  797.     for (long i= 0; i<len; i++) {
  798.         b= *pc++;
  799.         if (b == fromc) c= toc;
  800.         else c= b;
  801.         *pr++= c;
  802.         }    
  803.         
  804.     aSeq->UpdateFlds();
  805.     aSeq->Modified();
  806.     return aSeq;
  807. }
  808.  
  809.  
  810. DSequence* DSequence::Slide( long slideDist)
  811. /* insert "-" below (+dist) or above (-dist) of seq range,
  812.     squeeze out "-" above (below) of range
  813. */
  814. {     
  815.     long         slideSave, newlen, fulllen, len, i, j= 0;
  816.     char         b, cutchar, cutmask;
  817.     char        *pc, *pr;
  818.     
  819.     DSequence* aSeq= (DSequence*) Clone();    
  820.     if (fSelStart < 0) fSelStart= 0;
  821.     fulllen= aSeq->fLength;
  822.     len= fulllen - fSelStart;
  823.     Boolean domask= (fMasks && fMasksOk);
  824.     
  825.     if (slideDist < 0) {
  826.         // tough... do if below works...
  827.         // really need ability to extend seq in 5' (lower) direction 
  828.         //! build pr in reverse, then flip it....
  829.  
  830.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  831.         slideDist= -slideDist;
  832.         slideSave= slideDist;
  833.         aSeq->fBases= (char*) MemMore(aSeq->fBases, 2+fulllen+slideDist);
  834.         pr= aSeq->fBases;
  835.         pc= this->fBases + fulllen;
  836.         for (i= fulllen-1; i >= fSelStart+len; i--) *pr++= *--pc;
  837.              
  838.         if (pr == aSeq->fBases || *(pr-1) == indelEdge) cutchar= indelEdge;
  839.         else cutchar= indelSoft; //??
  840.         for (i=0; i<slideDist; i++) *pr++= cutchar;
  841.  
  842.         pc= this->fBases+fSelStart+len;
  843.         for (i= fSelStart+len-1; i >= fSelStart; i--) *pr++= *--pc;
  844.             
  845.         pc= this->fBases+fSelStart;
  846.         for (i= fSelStart-1; i>=0; i--) {
  847.             b= *--pc;
  848.             if (slideDist>0 && (b==indelSoft || b==indelEdge)) slideDist--;
  849.             else {
  850.                 *pr++= b;
  851.                 }
  852.             }
  853.  
  854.         newlen= pr - aSeq->fBases;
  855.         char* htmp= (char*) MemNew(newlen+1);
  856.         pc= htmp;
  857.         for (i=0; i<newlen; i++) *pc++= *--pr; //pr[j-i+1];
  858.         pc= '\0';
  859.         MemFree(aSeq->fBases);
  860.         aSeq->fBases = htmp;  
  861.         aSeq->fLength= newlen;
  862.         aSeq->fOrigin= fulllen - newlen; //== this->fLength - aSeq->fLength
  863.  
  864.         if (domask) {
  865.             slideDist= slideSave;
  866.             aSeq->fMasks= (char*) MemMore(aSeq->fMasks, 2+fulllen+slideDist);
  867.             pr= aSeq->fMasks;
  868.             pc= this->fMasks + fulllen;
  869.             for (i= fulllen-1; i >= fSelStart+len; i--) *pr++= *--pc;
  870.                  
  871.             cutmask= 0x80; // required empty mask  
  872.             for (i=0; i<slideDist; i++) *pr++= cutmask;
  873.     
  874.             pc= this->fMasks+fSelStart+len;
  875. #ifdef WIN_MSWIN
  876.             // mswin is crashing here for no obvious reason
  877.             //pc--; len--;
  878.             for (i= fSelStart + len - 1; i >= fSelStart; i--) {
  879.                  register short amask;
  880.                  --pc;
  881.                  amask= *pc;    //mswin bomb is here !
  882.                  *pr= amask;
  883.                  pr++;
  884.          }
  885. #else
  886.             for (i= fSelStart+len-1; i >= fSelStart; i--) *pr++= *--pc;
  887. #endif
  888.             pc= this->fMasks+fSelStart;
  889.             for (i= fSelStart-1; i>=0; i--) {
  890.                 b= *--pc;
  891.                 if (slideDist>0 && (b==cutmask)) slideDist--;
  892.                 else {
  893.                     *pr++= b;
  894.                     }
  895.                 }
  896.                 
  897.             newlen= pr - aSeq->fMasks;
  898.             htmp= (char*) MemNew(newlen+1);
  899.             pc= htmp;
  900.             for (i=0; i<newlen; i++) *pc++= *--pr; //pr[j-i+1];
  901.             pc= '\0';
  902.             MemFree(aSeq->fMasks);
  903.             aSeq->fMasks = htmp;  
  904.             }
  905.             
  906.         }    
  907.         
  908.     else if (slideDist > 0) {
  909.         fulllen= len;
  910.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  911.         aSeq->fBases= (char*) MemMore(aSeq->fBases, 2+fSelStart+fulllen+slideDist); //make it large enough
  912.  
  913.         pr= aSeq->fBases;
  914.       if (fSelStart==0 || pr[fSelStart-1]==indelEdge) cutchar= indelEdge; 
  915.         else cutchar= indelSoft; 
  916.  
  917.         pc= this->fBases+fSelStart;
  918.         pr= aSeq->fBases+fSelStart;
  919.  
  920.         for (j= 0; j<slideDist; j++) *pr++= cutchar;
  921.         for (i= 0; i<len; i++) *pr++= *pc++; 
  922.     
  923.         for (i= len; i<fulllen; i++) {
  924.             b= *pc++;
  925.             if (slideDist>0 && (b==indelSoft || b==indelEdge)) 
  926.                 slideDist--;
  927.             else {
  928.                 *pr++= b;
  929.                 }
  930.             }
  931.         
  932.         *pr= 0;
  933.         newlen= pr - aSeq->fBases; 
  934.         aSeq->fBases= (char*)MemMore(aSeq->fBases, newlen+1);  
  935.         
  936.         if (domask) {
  937.             aSeq->fMasks= (char*) MemMore(aSeq->fMasks, 2+fSelStart+fulllen+slideDist);
  938.           cutmask= 0x80; 
  939.             pc= this->fMasks+fSelStart;
  940.             pr= aSeq->fMasks+fSelStart;
  941.     
  942.             for (j= 0; j<slideDist; j++) *pr++= cutmask;
  943.             for (i= 0; i<len; i++) *pr++= *pc++; 
  944.  
  945.             for (i= len; i<fulllen; i++) {
  946.                 b= *pc++;
  947.                 if (slideDist>0 && (b==cutmask)) // this is BAD? must be done w/ base slide !?
  948.                     slideDist--;
  949.                 else {
  950.                     *pr++= b;
  951.                     }
  952.                 }
  953.             
  954.             *pr= 0;
  955.             newlen= pr - aSeq->fMasks; 
  956.             aSeq->fMasks= (char*)MemMore(aSeq->fMasks, newlen+1);  
  957.             }
  958.         }
  959.             
  960.     aSeq->UpdateFlds();
  961.     aSeq->Modified();
  962.     return aSeq;
  963. }
  964.  
  965.  
  966. DSequence* DSequence::Compress()
  967. // pull out "-", ".", ? anything but nuc/aa codes ? 
  968. {
  969.     long  len, fulllen, i;
  970.     char     b, c;
  971.     char * mc, * mr;
  972.     Boolean domask= (fMasks && fMasksOk);
  973.  
  974.     DSequence* aSeq= (DSequence*) Clone();    
  975.     if (fSelStart < 0) fSelStart= 0;
  976.     len= aSeq->fLength - fSelStart;
  977.     fulllen= len;
  978.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  979.     char* pc= this->fBases+fSelStart;
  980.     char* pr= aSeq->fBases+fSelStart;
  981.     if (domask) {
  982.         mc= this->fMasks+fSelStart;
  983.         mr= aSeq->fMasks+fSelStart;
  984.         }
  985.         
  986.     if (domask) for (i= 0; i<len; i++) {
  987.         b= *pc++;
  988.         c= *mc++;
  989.         if (b!=indelSoft && b!=indelEdge) { 
  990.             *pr++= b;
  991.             *mr++= c;
  992.             }
  993.         }
  994.     else for (i= 0; i<len; i++) {
  995.         b= *pc++;
  996.         if (b!=indelSoft && b!=indelEdge) 
  997.             *pr++= b;
  998.         }
  999.     for (i=len; i<fulllen; i++) *pr++= *pc++;
  1000.     if (domask) for (i=len; i<fulllen; i++) *mr++= *mc++;
  1001.  
  1002.     long newlen= pr - aSeq->fBases;
  1003.     aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen+1);
  1004.     aSeq->fBases[newlen]= 0;
  1005.     if (domask) {
  1006.         aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen+1);
  1007.         aSeq->fMasks[newlen]= 0;
  1008.         }
  1009.         
  1010.     aSeq->UpdateFlds();
  1011.     aSeq->Modified();
  1012.     return aSeq;
  1013. }
  1014.  
  1015.  
  1016. DSequence* DSequence::Translate(Boolean keepUnselected)
  1017. {    
  1018.     char  c;
  1019.     char    acodon[3];
  1020.     Boolean isrna, nocodon;
  1021.     char    *pr, *pc, *mr, *mc;
  1022.     long    len, fulllen, newlen, i, j, k;
  1023.     
  1024.     if (DCodons::NotAvailable()) return NULL;
  1025.     DSequence* aSeq= (DSequence*) Clone();        
  1026.     // !? what do we do w/ fMasks !?
  1027.     Boolean domask= (fMasks && fMasksOk);
  1028.     
  1029.     if (fSelStart < 0) fSelStart= 0;
  1030.     fulllen= this->fLength - fSelStart;
  1031.     len= fulllen;
  1032.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  1033.     
  1034.     switch (fKind) {
  1035.     
  1036.         case kRNA:
  1037.         case kDNA:
  1038.         case kNucleic: 
  1039.             {
  1040.             if (keepUnselected) {
  1041.                 pr= aSeq->fBases + fSelStart; // start at selection, leaving untranslated 5'
  1042.                 if (domask) mr= aSeq->fMasks + fSelStart;
  1043.                 }
  1044.             else {
  1045.                 pr= aSeq->fBases;
  1046.                  if (domask) mr= mr= aSeq->fMasks;
  1047.                  }
  1048.                  
  1049.             pc= this->fBases + fSelStart;
  1050.             if (domask) mc= this->fMasks + fSelStart;
  1051.             isrna= (fKind == kRNA);
  1052.             i= fSelStart;
  1053.             while (i < len) {
  1054.                 for (j=0; j<3; j++) {
  1055.                     c= toupper( *pc++);
  1056.                     if (isrna && c=='U') c= 'T';
  1057.                     acodon[j]= c;
  1058.                     }
  1059.                 i += 3;
  1060.                 for (k= 0, nocodon= true; k<64; k++) 
  1061.                     if ( MemCmp(DCodons::codon(k),acodon,3) == 0) { 
  1062.                         *pr++= DCodons::amino(k); //gCodonTable[k].amino;
  1063.                         nocodon= false;
  1064.                         break;
  1065.                         }
  1066.                 if (nocodon) *pr++= '?';
  1067.                 if (domask) {
  1068.                     *mr++= *mc;
  1069.                     mc += 3;
  1070.                     }
  1071.                 }
  1072.                  // copy over untranslated portion
  1073.             if (keepUnselected) {
  1074.                 long savei= i;
  1075.                 for ( ; i < fulllen; i++)  *pr++= *pc++; 
  1076.                 if (domask) for ( i= savei; i < fulllen; i++)  *mr++= *mc++; 
  1077.                 }
  1078.             }
  1079.             break;
  1080.             
  1081.         case kAmino: 
  1082.             {
  1083.             char *bestcodon;
  1084.             long  selend;
  1085.             
  1086.             if (len < fulllen) {
  1087.                 newlen= fulllen + len*3;
  1088.                 selend= fSelStart + len;
  1089.                 }
  1090.             else {
  1091.                 newlen= fulllen * 3;
  1092.                 selend= len;
  1093.                 }
  1094.             pc= this->fBases + fSelStart;
  1095.             aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen);
  1096.             if (keepUnselected)
  1097.                 pr= aSeq->fBases + fSelStart;
  1098.             else
  1099.                 pr= aSeq->fBases;
  1100.                 
  1101.             if (domask) {
  1102.                 mc= this->fMasks + fSelStart;
  1103.                 aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen);
  1104.                 if (keepUnselected)
  1105.                     mr= aSeq->fMasks + fSelStart;
  1106.                 else
  1107.                     mr= aSeq->fMasks;
  1108.                 }
  1109.                 
  1110.             for (i= fSelStart; i<selend; i++) {
  1111.                 c= toupper( *pc++);
  1112.                 bestcodon= (char*) DCodons::FindBestCodon(c);
  1113.                 MemCpy( pr, bestcodon, 3);  
  1114.                 pr += 3;
  1115.                 if (domask) {
  1116.                     for (j=0; j<3; j++) *mr++= *mc;
  1117.                     mc++;
  1118.                     }
  1119.                 }
  1120.                  // copy over untranslated portion
  1121.             if (keepUnselected) {
  1122.                 long savei= i;
  1123.                 for ( ; i < fulllen; i++)  *pr++= *pc++; 
  1124.                 if (domask) for ( i=savei; i < fulllen; i++)  *mr++= *mc++; 
  1125.                 }
  1126.             }
  1127.             break;
  1128.         
  1129.         default:
  1130.             return NULL;
  1131.          
  1132.       }
  1133.         
  1134.     *pr= '\0';
  1135.     newlen= pr - aSeq->fBases;
  1136.     aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen);
  1137.     if (domask) {
  1138.         *mr= '\0';
  1139.         newlen= mr - aSeq->fMasks;
  1140.         aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen);
  1141.         }
  1142.     aSeq->UpdateFlds();
  1143.     aSeq->Modified();
  1144.     return aSeq;    
  1145. }
  1146.  
  1147.  
  1148. //Boolean domask= (fMasks && fMasksOk);
  1149.  
  1150.  
  1151. void DSequence::DoWrite(DFile* aFile, short format)
  1152. {  
  1153.     if (fLength>0) {
  1154.         DSeqFile::WriteSeqWrapper( aFile, fBases, fLength, format, fName);
  1155.         if (fMasks && fMasksOk && DSeqFile::gWriteMasks) 
  1156.             DSeqFile::WriteMaskWrapper( aFile, fMasks, fLength, format, fName);
  1157.         }
  1158. }
  1159.  
  1160.  
  1161. void DSequence::DoWriteSelection(DFile* aFile, short format)
  1162. {
  1163.     if (fSelBases==0) 
  1164.         DoWrite( aFile, format);
  1165.     else if (fLength>0) {
  1166.         long aStart= Min( fSelStart, fLength);
  1167.         long aLength= Min( fSelBases, fLength - fSelStart);
  1168.         DSeqFile::WriteSeqWrapper(  aFile, fBases+aStart, aLength, format, fName);
  1169.         if (fMasks && fMasksOk && DSeqFile::gWriteMasks)  
  1170.             DSeqFile::WriteMaskWrapper( aFile, fMasks+aStart, aLength, format, fName);
  1171.         }
  1172. }
  1173.  
  1174.  
  1175.  
  1176.  
  1177. Boolean DSequence::GoodChar(char& aChar) 
  1178. {
  1179.     char* aacodes = gAminos;
  1180.     char* iupaccodes = gIubbase;
  1181.     char* nacodes = gPrimenuc;
  1182.     char    c;
  1183.     char* codes = NULL;
  1184.  
  1185.   if (aChar=='\n' || aChar=='\r')  
  1186.         return FALSE;
  1187.     else if (aChar<' ' || aChar>'~')  
  1188.         return TRUE; //allow return,tab,delete, ? option chars
  1189.  
  1190.   switch (fKind) {
  1191.       case kDNA            :
  1192.         case kRNA            : codes= nacodes; break;
  1193.         case kNucleic    : codes= iupaccodes; break;
  1194.         case kAmino        : codes= aacodes; break;
  1195.         default:
  1196.       case kOtherSeq: return TRUE;
  1197.         }
  1198.         
  1199.   c= toupper(aChar);
  1200.     while (*codes) {
  1201.         if (c == *codes) {
  1202.           switch (fKind) {
  1203.                 case kDNA: if (c == 'U') {
  1204.                     if (aChar=='u') aChar= 't'; else aChar= 'T';
  1205.                     }
  1206.                 break;
  1207.                 case kRNA: if (c == 'T') {
  1208.                     if (aChar=='t') aChar= 'u'; else aChar= 'U';
  1209.                     }
  1210.                 break;
  1211.                 }
  1212.             return TRUE;
  1213.             }
  1214.         codes++;
  1215.         }
  1216.     return FALSE;
  1217. }
  1218.  
  1219.  
  1220. Boolean DSequence::IsConsensus()
  1221. {
  1222.     return (fName && StringCmp(fName,kConsensus)==0);
  1223. }
  1224.  
  1225.  
  1226.  
  1227. DSequence* MakeSequence(char* name, char* bases, char* info, long modtime)
  1228. {
  1229.     DSequence* aSeq= new DSequence();
  1230.     aSeq->SetName(name);
  1231.     //?? can we always assume bases is null terminated?
  1232.     aSeq->SetBases(bases);
  1233.     aSeq->SetInfo(info);
  1234.      if (modtime!=0) aSeq->SetTime( (unsigned long)modtime);
  1235.     aSeq->UpdateFlds();      
  1236.     return aSeq;
  1237. }
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243. long DSequence::SearchAgain() 
  1244. {
  1245.     return Search( "", FALSE);
  1246. }
  1247.  
  1248.  
  1249.  
  1250. void DSequence::SearchORF( long& start, long& stop) 
  1251. {
  1252.     char  startc[2];
  1253.     long  i, j, k;
  1254.     short    ns;
  1255.     CodonStat  stops[10];
  1256.     
  1257.     start= kSearchNotFound;
  1258.     stop = kSearchNotFound;
  1259.     if (DCodons::NotAvailable()) return;
  1260.     
  1261.     for (ns= 0, i= 0; i<64; i++) {
  1262.         if (ns<10 && DCodons::amino(i) == '*') 
  1263.             stops[ns++] = DCodons::fCodons[i];
  1264.         }
  1265.     if (ns == 0) return;
  1266.         
  1267.     switch (fKind) {  
  1268.         case kRNA:
  1269.         case kDNA:
  1270.         case kNucleic: 
  1271.              start= Search( DCodons::startcodon(), FALSE);
  1272.              if (start == kSearchNotFound) return;
  1273.              for (j= start+3; j<fLength; j += 3) {
  1274.                  for (k=0; k<ns; k++) {
  1275.                      if (StrNICmp( fBases+j, stops[k].codon, 3) == 0) {
  1276.                          stop= j+3; // +3 to include this codon
  1277.                          return;
  1278.                          }
  1279.                      }
  1280.                  }
  1281.             break;
  1282.             
  1283.         case kAmino:
  1284.             startc[0]= DCodons::startamino();
  1285.             startc[1]= 0;
  1286.              start= Search( startc, FALSE);
  1287.              if (start == kSearchNotFound) return;
  1288.              for (j= start+1; j<fLength; j++) {
  1289.                  for (k=0; k<ns; k++) {
  1290.                      if (toupper(fBases[j]) == toupper(stops[k].amino)) {
  1291.                          stop= j+1; // +1 to include this codon
  1292.                          return;
  1293.                          }
  1294.                      }
  1295.                  }
  1296.             break;
  1297.             
  1298.         default:
  1299.             break;
  1300.         }
  1301. }
  1302.  
  1303.  
  1304.  
  1305. void DSequence::NucleicSearch(char* source, char* target, SearchRec& aSearchRec)
  1306. {
  1307.     long k, j, tBits, lens, ti;
  1308.     Boolean done;
  1309.  
  1310.                     //find target[ti] where tBits == kMaskA,C,G,T for fastest search
  1311.                     //This part is wasted time for SearchAgain... store tBits/ti in saverec...
  1312.     lens= StrLen(target);
  1313.     for (j= 0, ti= 0, tBits= 0; j<lens && !tBits; j++) {
  1314.         ti= j;
  1315.         tBits= NucleicBits( target[ti]);
  1316.         tBits &= kMaskNucs; //    bClr( tBits, kBitExtra); //drop RNA bit
  1317.         }
  1318.  
  1319.     do {
  1320. reloop:
  1321.             aSearchRec.indx += aSearchRec.step; 
  1322.             aSearchRec.lim  -= aSearchRec.step;    
  1323.             
  1324.             if (aSearchRec.step>0) {
  1325.                 for (j= 0; j<aSearchRec.lim; j++)
  1326.                  // if (IsNucleicMatch( tBits, NucleicBits( source[j+aSearchRec.indx]))) 
  1327.                  if ( tBits & NucleicBits( source[j+aSearchRec.indx]) ) 
  1328.                  {
  1329.                     k= j; 
  1330.                     goto nextindx;
  1331.                  }
  1332.                 k= aSearchRec.lim;
  1333.                 }            
  1334.             else {  //step<0 IS BAD .. see UTextDoc version...
  1335.                 for (j= 0; j > -aSearchRec.lim; j--) 
  1336.                   //if (IsNucleicMatch( tBits, NucleicBits( source[j+aSearchRec.indx])))
  1337.                   if ( tBits & NucleicBits( source[j+aSearchRec.indx]) ) 
  1338.                 {
  1339.                     k= j; 
  1340.                     goto nextindx;
  1341.                     }
  1342.                 k= -aSearchRec.lim;
  1343.                 }
  1344.                 
  1345. nextindx:  
  1346.             aSearchRec.indx += k; 
  1347.             aSearchRec.lim  -= k;
  1348.                 //? not enough source left to match full target 
  1349.             if (aSearchRec.step>0) {
  1350.                 if (aSearchRec.lim < lens-ti) aSearchRec.lim= 0;
  1351.                 }            
  1352.             else {
  1353.                 if (aSearchRec.lim < ti) aSearchRec.lim= 0; //? or lim < ti-1 
  1354.                 }
  1355.             done= (aSearchRec.lim==0);
  1356.             
  1357.             if (!done) {
  1358.                 long srcstart= aSearchRec.indx - ti;
  1359.                 for (j= 0; j<lens; j++) 
  1360.                  if (j != ti) {
  1361.                     //if (!IsNucleicMatch( NucleicBits( target[j]), NucleicBits( source[j+srcstart]))) 
  1362.                   if (!(kMaskNucs & NucleicBits( target[j]) & NucleicBits( source[j+srcstart]))) 
  1363.                       goto reloop;
  1364.                     }
  1365.                 done= true;
  1366.                 }
  1367.         } while (!done);
  1368. }  
  1369.     
  1370.  
  1371. void DSequence::ProteinSearch(char* source, char* target, SearchRec& aSearchRec)
  1372. {
  1373.     //just toupper match of chars 
  1374.     char      tChar; 
  1375.     Boolean  done;
  1376.     long        lens, k, j;
  1377.  
  1378.     lens= StrLen( target);
  1379.     tChar= toupper( target[0]);
  1380.     
  1381.     do {
  1382. reloop:
  1383.             aSearchRec.indx += aSearchRec.step; 
  1384.             aSearchRec.lim  -= aSearchRec.step;    
  1385.             
  1386.             if (aSearchRec.step>0) {
  1387.                 for (j= 0; j<aSearchRec.lim; j++) 
  1388.                  if (tChar == toupper( source[j+aSearchRec.indx])) {
  1389.                     k= j;
  1390.                     goto nextindx;
  1391.                     }
  1392.                 k= aSearchRec.lim;
  1393.                 }            
  1394.             else {
  1395.                 for (j= 0; j > -aSearchRec.lim; j--)
  1396.                  if (tChar == toupper(source[j+aSearchRec.indx])) {
  1397.                     k= j; 
  1398.                     goto nextindx;
  1399.                     }
  1400.                 k= -aSearchRec.lim;
  1401.                 }
  1402.                 
  1403. nextindx:  
  1404.             aSearchRec.indx += k; 
  1405.             aSearchRec.lim  -= k;
  1406.                 //? not enough source left to match full target 
  1407.             if (aSearchRec.step>0) {
  1408.                 if (aSearchRec.lim < lens-1) aSearchRec.lim= 0;
  1409.                 }            
  1410.             else {
  1411.                 if (aSearchRec.lim < 1) aSearchRec.lim= 0;  
  1412.                 }
  1413.             done= (aSearchRec.lim==0);
  1414.             
  1415.             if (!done) {
  1416.                 for (j= 1; j<lens; j++) {
  1417.                     if (toupper( target[j]) != toupper( source[j+aSearchRec.indx])) 
  1418.                         goto reloop;
  1419.                     }
  1420.                 done= true;
  1421.                 }
  1422.         } while (!done);
  1423. }  
  1424.  
  1425.  
  1426.     
  1427.  
  1428. long DSequence::Search( char* target, Boolean backwards)
  1429. /* search for target in sequence;
  1430.     search == abs index into fBases[0..fLength] or kSearchNotFound
  1431.   if (target='') then find next  
  1432.   if (backwards) then backwards search
  1433. */
  1434. {
  1435.     long        limit, aStart;
  1436.     SearchRec  aSearchRec;
  1437.  
  1438.     aStart= fSelStart;
  1439.     if (!target || !*target) {  //search again
  1440.         if (fSearchRec.targ && (fSearchRec.step == -1 || fSearchRec.step == 1)) {  
  1441.             aSearchRec= fSearchRec;
  1442.             target= aSearchRec.targ;
  1443.             }        
  1444.         else {
  1445.             return kSearchNotFound;
  1446.             }
  1447.         }        
  1448.     else {
  1449.         limit= fLength; //StrLen(fBases);
  1450.         if (aStart < 0) aStart= 0;
  1451.         if (backwards) {
  1452.             if (!aStart) aStart= limit-1;
  1453.             else limit= aStart+1;  //? off-by-one ??
  1454.             }        
  1455.         else {
  1456.             if (aStart > limit) aStart= 0; 
  1457.             else limit -= aStart;
  1458.             }
  1459.         if (fSelBases > 0 && fSelBases < limit) limit= fSelBases;
  1460.         if (backwards) aSearchRec.step= -1;
  1461.         else aSearchRec.step= 1;
  1462.         aSearchRec.indx= aStart - aSearchRec.step;  //indx always in [0..handsize-1], except 1st is -1 
  1463.         aSearchRec.lim = limit + aSearchRec.step;  //lim always in [1..handsize] or 0=done, except 1st is hand+1 
  1464.         aSearchRec.targ= StrDup(target);
  1465.         }
  1466.  
  1467.     switch (fKind) {  
  1468.         case kRNA:
  1469.         case kDNA:
  1470.         case kNucleic: 
  1471.             NucleicSearch(fBases,target,aSearchRec); 
  1472.             break;
  1473.         default:
  1474.             ProteinSearch(fBases,target,aSearchRec);
  1475.             break;
  1476.         }
  1477.     
  1478.     fSearchRec= aSearchRec;
  1479.     if (aSearchRec.lim == 0) return kSearchNotFound;
  1480.     else return aSearchRec.indx;
  1481. }  
  1482.  
  1483.  
  1484.